package com.itlong.cloud.controller;

import com.itlong.cloud.POJO.DTO.property.PropertyUserLoginDTO;
import com.itlong.cloud.POJO.PO.PropertyRolePO;
import com.itlong.cloud.POJO.PO.PropertyUserInfoPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.operate.OperateGetRoleMenuVO;
import com.itlong.cloud.POJO.VO.property.PropertyProjectRoleVO;
import com.itlong.cloud.POJO.VO.property.PropertyUserCacheVO;
import com.itlong.cloud.POJO.VO.property.PropertyUserLoginCheckVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.abstracts.BaseController;
import com.itlong.cloud.annotation.LoggerInfo;
import com.itlong.cloud.annotation.UnAuthAccessRequired;
import com.itlong.cloud.constants.LogDescConstant;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.enumerate.UserLoginDescEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.PropertyErrorCodeEnum;
import com.itlong.cloud.project.operate.IOperateProjectServiceClient;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.user.property.IPropertyRoleServiceClient;
import com.itlong.cloud.user.property.IPropertyUserServiceClient;
import com.itlong.cloud.utils.encrypt.Md5;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <desc>
 *      物业登录相关Controller
 * </desc>
 *
 * @createDate 2017/10/12
 */
@RestController
@RefreshScope
public class PropertyLoginController extends BaseController{

    private static Logger LOG = LoggerFactory.getLogger(PropertyLoginController.class);

    //物业人员服务层暴露接口
    @Autowired
    IPropertyUserServiceClient iPropertyUserServiceClient;

    @Autowired
    IPropertyRoleServiceClient iPropertyRoleServiceClient;

    @Autowired
    IOperateProjectServiceClient iOperateProjectServiceClient;

    @Value("${" + PlatformConstants.PROPERTY_USER_TOKEN_KEY + "}")
    String userTokenKey;


    /**
     * <desc>
     *      物业人员登录（物业人员账号或物业管理员帐号+密码  或者projectId+物业管理员密码登录）
     * <desc/>
     * @param   propertyUserLoginDTO     物业用户登录DTO
     * @return  MessageVO    标准格式化响应结果
     * @author Biao.R
     * @createDate 2017/10/12
     */
    @LoggerInfo(identifer = "login")
    @PostMapping("/login")
    @ResponseBody
    //@LoggerInfo(operateDesc = LogDescConstant.USER_PROPERTY_LOGIN_LOG_DESC)
    public Object login(PropertyUserLoginDTO propertyUserLoginDTO) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        propertyUserLoginDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyUserLoginDTO.class, request);
        try {
            if (propertyUserLoginDTO == null) {
                request.setAttribute("checkMessage",BaseErrorCodeEnum.NOT_PARAM.getErrorCode().getCodeMsg());
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String account = propertyUserLoginDTO.getAccount();
            String password = propertyUserLoginDTO.getPassword();
            if (StringUtils.isBlank(account) || StringUtils.isBlank(password)) {
                request.setAttribute("checkMessage",PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_EMPTY_ERR.getErrorCode().getCodeMsg());
                return new MessageVO(PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_EMPTY_ERR.getErrorCode());
            }
            //解密密码
            String passwordStr = UserTokenUtil.getPassword(password,userTokenKey);
            //LOG.info("【物业登录userTokenKey】:"+userTokenKey);
            //LOG.info("【物业登录passwordStr】:"+passwordStr);
            propertyUserLoginDTO.setPassword(passwordStr);
            //PropertyUserInfoPO propertyUserInfoPO = iPropertyUserServiceClient.checkUser(propertyUserLoginDTO);

            PropertyUserInfoPO propertyUserInfoPO = null;
            //登录前，先检查账号有没有被锁定
            MessageVO checkLockMessage = iPropertyUserServiceClient.getAccountLockDetail(account);
            if (checkLockMessage != null) {
                request.setAttribute("checkMessage",checkLockMessage);
                return checkLockMessage;
            }
            if (account.matches(PlatformConstants.PROJECTID_REGEX)) {
                //一卡通 通过项目编号+管理员密码登录
                Map<String, Object> param = new HashMap<>();
                param.put("projectId", account);
                param.put("password", Md5.En(propertyUserLoginDTO.getPassword()));
                propertyUserInfoPO = iPropertyUserServiceClient.checkUserByProjectId(param);
            } else {
                //物业人员账号或物业管理员帐号+密码登录
                Map<String, String> param = new HashMap<>();
                param.put("userName", account);
                param.put("password", Md5.En(passwordStr));
                propertyUserInfoPO = iPropertyUserServiceClient.checkUserByUserName(param);
            }

            if (propertyUserInfoPO == null) {
                //账号或密码错误，累计5次
                MessageVO messageVO = iPropertyUserServiceClient.loginErrorHandler(propertyUserLoginDTO);
                request.setAttribute("checkMessage",messageVO.getMsg());
                return messageVO;
            }

            //查询该人员所属的项目是否被禁用
            List<Integer> projectStatusList = iPropertyUserServiceClient.getProjectByUserId(propertyUserInfoPO.getUserId());
            if(projectStatusList!=null && !projectStatusList.isEmpty()){
                boolean projectBanFlag = false;
                //所有项目都是禁用状态，提示项目被禁用
                for (Integer status : projectStatusList) {
                    if (status == DataStatusEnum.NORMAL.getType()) {
                        projectBanFlag = true;
                    }
                }
                if (!projectBanFlag) {
                    request.setAttribute("checkMessage",PropertyErrorCodeEnum.PUB_LOGIN_PROJECT_STATUS_IS_UNABLE.getErrorCode().getCodeMsg());
                    return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_PROJECT_STATUS_IS_UNABLE.getErrorCode());
                }
            }

            //查询帐号状态是否被禁用或删除
            Integer userStatus = propertyUserInfoPO.getStatus();
            if (userStatus != null) {
                if (userStatus == DataStatusEnum.BAN.getType()) {
                    request.setAttribute("checkMessage",PropertyErrorCodeEnum.PUB_LOGIN_ACCOUNT_STATUS_IS_BAN.getErrorCode().getCodeMsg());
                    return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ACCOUNT_STATUS_IS_BAN.getErrorCode());
                }
                if (userStatus == DataStatusEnum.DELETE.getType()) {
                    request.setAttribute("checkMessage",PropertyErrorCodeEnum.PUB_LOGIN_ACCOUNT_STATUS_IS_DELETE.getErrorCode().getCodeMsg());
                    return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ACCOUNT_STATUS_IS_DELETE.getErrorCode());
                }
            }

            //校验用户成功后，获取登录所需数据
            PropertyUserLoginCheckVO loginDetail = iPropertyUserServiceClient.getLoginDetail(propertyUserInfoPO);
            List<PropertyProjectRoleVO> projectRoleVOList = loginDetail.getProjectRoleVOList();
            if (projectRoleVOList == null || projectRoleVOList.isEmpty()) {
                request.setAttribute("checkMessage",PropertyErrorCodeEnum.PUB_PROJECT_ROLE_ERR.getErrorCode().getCodeMsg());
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ROLE_ERR.getErrorCode());
            }
            request.setAttribute("checkMessage",UserLoginDescEnum.SUCCESS.getDescription());
            request.setAttribute("loginUser",loginDetail);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), loginDetail);
        } catch (Exception e) {
            request.setAttribute("checkMessage","【物业_公共_登录】登录查询失败");
            throw new DataAccessException("【物业_公共_登录】登录查询失败", e);
        }
    }


    /**
     * <desc>
     *      物业人员注销
     * <desc/>
     * @param   propertyUserLoginDTO     物业用户登录DTO
     * @return  MessageVO    标准格式化响应结果
     * @author Biao.R
     * @createDate 2017/10/12
     */
    @PostMapping("/logout")
    @ResponseBody
    @LoggerInfo(operateDesc = LogDescConstant.USER_PROPERTY_LOGOUT_LOG_DESC)
    public Object logout(PropertyUserLoginDTO propertyUserLoginDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyUserLoginDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyUserLoginDTO.class, request);
            if (propertyUserLoginDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            PropertyUserCacheVO cacheVO = iPropertyUserServiceClient.logout(propertyUserLoginDTO);
            if (cacheVO == null) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGOUT_FAIL.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业_公共_注销】物业注销失败", e);
        }
    }

    /**
     * <desc>
     *      登陆成功后获取菜单
     * <desc/>
     * @param   propertyUserLoginDTO     物业用户登录DTO
     * @return  MessageVO    标准格式化响应结果
     * @author Biao.R
     * @createDate 2017/10/12
     */
    @PostMapping("/getFunctions")
    @ResponseBody
    @LoggerInfo(operateDesc = LogDescConstant.USER_PROPERTY_GETFUNCTIONS_LOG_DESC)
    public Object getFunctions(PropertyUserLoginDTO propertyUserLoginDTO) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyUserLoginDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyUserLoginDTO.class, request);
            if (propertyUserLoginDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String roleId = propertyUserLoginDTO.getRoleId();
            String projectId = propertyUserLoginDTO.getProjectId();
            if (StringUtils.isBlank(projectId) || StringUtils.isBlank(roleId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ROLE_ERR.getErrorCode());
            }
            //查询角色启用状态:若该角色已被禁用，则不能登录
            Map<String, Object> params = new HashMap<>();
            params.put("projectId", projectId);
            params.put("roleId", roleId);
            params.put("status", DataStatusEnum.NORMAL.getType());
            params.put("mark", "noGroupId");
            List<PropertyRolePO> roleList = iPropertyRoleServiceClient.getByFields(params);
            if (roleList == null || roleList.isEmpty()) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ROLE_STATUS_IS_UNABLE.getErrorCode());
            }
            List<OperateGetRoleMenuVO> menus = iPropertyRoleServiceClient.getFunctions(propertyUserLoginDTO);
            if (menus == null || menus.isEmpty()) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_MENU_IS_NULL.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), menus);
        } catch (Exception e) {
            throw new DataAccessException("【物业_公共_登录】获取菜单资源失败", e);
        }
    }

    /**
     * <desc>
     *      点击左边菜单后，根据角色获取按钮权限
     * <desc/>
     * @param   propertyUserLoginDTO     物业用户登录DTO
     * @param   identifier     页面按钮对应的权限标识
     * @return  MessageVO    标准格式化响应结果
     * @author Biao.R
     * @createDate 2017/10/12
     */
    @PostMapping("/getAuthBtns")
    @ResponseBody
    public Object getAuthBtns(PropertyUserLoginDTO propertyUserLoginDTO, String identifier) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyUserLoginDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyUserLoginDTO.class, request);
            identifier = request.getAttribute("identifier") == null ? null : request.getAttribute("identifier").toString();
            String roleId = propertyUserLoginDTO.getRoleId();
            String functionId = propertyUserLoginDTO.getFunctionId();
            //对于页面中由按钮跳指向页面的跳转，需要由按钮的identifier  获取对应二级菜单的functionId
            if (StringUtils.isEmpty(functionId) && StringUtils.isNotEmpty(identifier)) {
                //通过component和roleId  反向获取对应菜单functionId
                functionId = iPropertyRoleServiceClient.getFunctionIdByIdentifier(identifier);
            }
            if (StringUtils.isBlank(roleId) || StringUtils.isBlank(functionId)) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ROLE_FUNCTIONID_ILLEGAL.getErrorCode());
            }
            propertyUserLoginDTO.setFunctionId(functionId);
            List<OperateGetRoleMenuVO> functionList = iPropertyRoleServiceClient.getAuthBtns(propertyUserLoginDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), functionList);
        } catch (Exception e) {
            throw new DataAccessException("【物业_公共_登录】获取菜单下的按钮失败", e);
        }
    }

    /**
     * <desc>
     *     登录成功后根据userid查询当前用户下的小区信息
     * <desc/>
     *@param  token
     * @return  MessageVO 标准格式化响应结果
     * @author JuGuang.S
     * @createDate 2018/07/04
     */
    @ResponseBody
    @PostMapping(path = "/getUserProjectInfo")
    public Object getUserProjectInfo(String token,String loginUserId) throws Exception {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            token = request.getAttribute("token") == null ? null : request.getAttribute("token").toString();
            loginUserId = request.getAttribute("loginUserId") == null ? null : request.getAttribute("loginUserId").toString();
            if (StringUtils.isEmpty(loginUserId)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            List<PropertyProjectRoleVO> projectRoles = iPropertyUserServiceClient.getUserProjectInfo(loginUserId);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), projectRoles);
        } catch (Exception e) {
            throw new DataAccessException("【物业_用户_通行记录】分页查询失败", e);
        }
    }

    /**
     * <desc>
     *      找回密码时，通过账号获取绑定手机号
     * <desc/>
     *
     * @return MessageVO 标准格式化响应结果
     * @author wangzhi
     * @createDate 2019/12/25
     */
    @UnAuthAccessRequired
    @ResponseBody
    @PostMapping(path = "/getPhoneNumByUserName")
    public Object getPhoneNumByUserName(){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String userName = request.getAttribute("userName") == null ? null : request.getAttribute("userName").toString();
            if (StringUtils.isBlank(userName)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            Map<String, Object> resultData = iPropertyUserServiceClient.getPhoneNumByUserName(userName);
            if (resultData == null || resultData.isEmpty()) {
                return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(), "抱歉，您的账号暂不支持重置密码,请联系管理员！");
            }
            if (resultData.get("result") != null) {
                return new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(), "账号不存在");
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), resultData.get("administratorPhone"));
        } catch (Exception e) {
            throw new DataAccessException("【物业_用户_忘记密码】获取绑定手机号失败", e);
        }
    }

}
